<?php
/**
 *
 * @package Legacy
 * @version $Id: Legacy_Module.class.php,v 1.6 2008/09/25 15:11:59 kilica Exp $
 * @copyright Copyright 2005-2007 XOOPS Cube Project  <http://xoopscube.sourceforge.net/> 
 * @license http://xoopscube.sourceforge.net/license/GPL_V2.txt GNU GENERAL PUBLIC LICENSE Version 2
 *
 */

 /**
  * @public
  * @brief [Abstract] Represents modules and used for Legacy_Controller
  * 
  * This is an abstract class which has interfaces to connect with the controller about
  * the module process. Legacy controller makes an interface of this class and uses its
  * methods to call module programs.
  * 
  * So modules may define their sub-classes implementing this interface.
  * The instance is attached to the Legacy_Context after initializing, so modules can
  * defines members for module's features and can access them. But, most interfaces
  * defined by this class should be called by only Legacy_Controller.
  * 
  * @attention
  *    This interfaces are initialized by only Legacy_Controller.
  * 
  * @see Legacy_Utils::createModule()
  * @see XoopsModule
  */
class Legacy_AbstractModule
{
	/**
	 * @public
	 * @brief [READ ONLY] Map Array - std::map<string, mixed> - used freely for this module.
	 * @remarks
	 *    If references are must, access directly to this member.
	 */
	var $mAttributes = array();
	
	/**
	 * @public
	 * @brief [READ ONLY] XoopsModule
	 */
	var $mXoopsModule = null;
	
	/**
	 * @public
	 * @brief [READ ONLY] Map Array - std::map<string, string>
	 */
	var $mModuleConfig = array();
	
	/**
	 * @private
	 * @brief Legacy_AbstractCacheInformation - The cached instance.
	 * @see getCacheInfo()
	 */
	var $mCacheInfo = null;
	
	/**
	 * @private
	 * @brief XCube_RenderTarget - The render target instance for this module.
	 * @see getRenderTarget()
	 */
	var $mRender = null;
	
	/**
	 * @public
	 * @brief constructor
	 * @param $module XoopsModule
	 * @attention
	 *     Basically, only Legacy_Controller and its utility functions should call the
	 *     constructor.
	 */
	function Legacy_AbstractModule(&$module)
	{
		$this->setXoopsModule($module);
		
		if ($module->get('hasconfig') == 1 || $module->get('hascomments') == 1 || $module->get('hasnotification') == 1) {
			$handler =& xoops_gethandler('config');
			$this->setModuleConfig($handler->getConfigsByCat(0, $module->get('mid')));
		}
	}

	/**
	 * @public
	 * @brief Sets $value with $key to attributes.
	 * @param $key string
	 * @param $value mixed
	 * @return void
	 * @remarks
	 *    If references are must, access directly to $mAttributes. Because PHP4 can't
	 *    handle reference in the signature of this member function.
	 */
	function setAttribute($key, $value)
	{
		$this->mAttributes[$key] = $value;
	}

	/**
	 * @public
	 * @brief Gets a value indicating whether the value specified by $key exists.
	 * @param $key string
	 * @return bool
	 */	
	function hasAttribute($key)
	{
		return isset($this->mAttributes[$key]);
	}
	
	/**
	 * @public
	 * @brief Gets a value of attributes with $key.
	 * @param string $key
	 * @return mixed - If the value specified by $key doesn't exist in attributes, returns null.
	 */
	function getAttribute($key)
	{
		return isset($this->mAttributes[$key]) ? $this->mAttributes[$key] : null;
	}

	/**
	 * @public
	 * @brief Binds an instance of XoopsModule to the property.
	 * @param $xoopsModule XoopsModule
	 * @return void
	 */	
	function setXoopsModule(&$xoopsModule)
	{
		$this->mXoopsModule =& $xoopsModule;
	}
	
	/**
	 * @public
	 * @brief Gets the binded XoopsModule instance.
	 * @return XoopsModule
	 */
	function &getXoopsModule()
	{
		return $this->mXoopsModule;
	}
	
	/**
	 * @public
	 * @brief Binds array of xoops module config to the property.
	 * @param $config Map Array - std::map<string, mixed>
	 * @return void 
	 */
	function setModuleConfig($config)
	{
		$this->mModuleConfig = $config;
	}

	/**
	 * @public
	 * @brief Gets a value form xoops module config with $key. 
	 * @param $key string
	 * @return mixed If $key is specified null, returns map array (std::map<string, mixed>)
	 */
	function getModuleConfig($key = null)
	{
		if ($key == null) {
			return $this->mModuleConfig;
		}
		
		return isset($this->mModuleConfig[$key]) ? $this->mModuleConfig[$key] : null;
	}

	/**
	 * @public
	 * @brief Gets the cache information instance.
	 * @return Legacy_ModuleCaceInformation
	 * @see _createChaceInfo()
	 */	
	function &getCacheInfo()
	{
		if (!is_object($this->mCacheInfo)) {
			$this->_createCacheInfo();
		}
		
		return $this->mCacheInfo;
	}
	
	/**
	 * @protected
	 * @brief Creates a cache information instance and returns it.
	 * @return Legacy_ModuleCacheInformation
	 * @remarks
	 *     This member function sets the created instance to mCacheInfo because this
	 *     instance has to keep the instance for many callbacks.
	 * @see getCacheInfo()
	 */
	function _createCacheInfo()
	{
		$this->mCacheInfo =& new Legacy_ModuleCacheInformation();
		$this->mCacheInfo->mURL = xoops_getenv('REQUEST_URI');
		$this->mCacheInfo->setModule($this->mXoopsModule);
	}
	
	/**
	 * @public
	 * @brief Gets the render target instance.
	 * @return XCube_RenderTarget
	 * @see _createRenderTarget()
	 */
	function &getRenderTarget()
	{
		if ($this->mRender == null) {
			$this->_createRenderTarget();
		}
		
		return $this->mRender;
	}

	/**
	 * @protected
	 * @brief Creates a render target instance and returns it.
	 * @return XCube_RenderTarget
	 * @remarks
	 *     This member function sets the created instance to mRender because this
	 *     instance has to keep the instance for many callbacks.
	 * @see getRenderTarget()
	 */	
	function _createRenderTarget()
	{
		$renderSystem =& $this->getRenderSystem();
		
		$this->mRender =& $renderSystem->createRenderTarget('main');
		if ($this->mXoopsModule != null) {
			$this->mRender->setAttribute('legacy_module', $this->mXoopsModule->get('dirname'));
		}
	}
	
	/**
	 * @public
	 * @brief Gets a name of the dependency render system.
	 * @return string
	 * @remarks
	 *     If this module depends on other systems than the main render system  by Legacy,
	 *     override this.
	 * @see getRenderSystem()
	 */
	function getRenderSystemName()
	{
		$root =& XCube_Root::getSingleton();
		return $root->mContext->mBaseRenderSystemName;
	}
	
	/**
	 * @public
	 * @brief Gets the dependency render system.
	 * @return XCube_RenderSystem
	 * @remarks
	 *     If this module uses the unregistered render system is used, override this.
	 */
	function &getRenderSystem()
	{
		$root =& XCube_Root::getSingleton();
		$renderSystem =& $root->getRenderSystem($this->getRenderSystemName());
		
		return $renderSystem;
	}
	
	/**
	 * @public
	 * @brief Gets a value indicating whether this modules is an active.
	 * @return bool
	 */
	function isActive()
	{
		if (!is_object($this->mXoopsModule)) {	//< FIXME
			return false;
		}
		
		return $this->mXoopsModule->get('isactive') ? true : false;
	}
	
	/**
	 * @public
	 * @brief Gets a value indicating whether the current module has a option of
	 *        configurations to use the cache system.
	 * @return bool
	 */
	function isEnableCache()
	{
		if (xoops_getenv('REQUEST_METHOD') == 'POST') {
			return false;
		}
		
		$root =& XCube_Root::getSingleton();
		
		return is_object($this->mXoopsModule) && !empty($root->mContext->mXoopsConfig['module_cache'][$this->mXoopsModule->get('mid')]);
	}
	
	/**
	 * @public
	 * @brief Initializes a cache information object, and returns it.
	 * @return Legacy_ModuleCacheInformation
	 */
	function &createCacheInfo()
	{
		$this->mCacheInfo =& new Legacy_ModuleCacheInformation();
		$this->mCacheInfo->mURL = xoops_getenv('REQUEST_URI');
		$this->mCacheInfo->setModule($this->mXoopsModule);
		
		return $this->mCacheInfo;
	}

	/**
	 * @public
	 * @brief [Abstract] This method is called by the controller strategy, if this module
	 *        is the current module.
	 * @return void
	 */	
	function startup()
	{
	}
	
	/**
	 * @public
	 * @brief [Abstract] This method is called back by the action search feature in the
	 *        control panel.
	 * @param Legacy_ActionSearchArgs $searchArgs
	 * @return void
	 * @see Legacy_ActionSearchArgs
	 */
	function doActionSearch(&$searchArgs)
	{
	}
	
	/**
	 * @public
	 * @brief This method is called back by the xoops global search feature.
	 */
	function doLegacyGlobalSearch($queries, $andor, $max_hit, $start, $uid)
	{
	}
	
	/**
	 * @public
	 * @brief Gets a value indicating whether this module has the page controller in
	 *        the control panel side.
	 * @return bool
	 * @note
	 *    Side menu blocks may not display the admin menu if this member function returns
	 *    false.
	 * @attention
	 *    Controller fetches the list of modules from DB before. So, 'override' may not be
	 *    able to change the process.
	 */
	function hasAdminIndex()
	{
		return false;
	}
	
	/**
	 * @public
	 * @brief [Abstract] Gets an absolute URL indicating the top page of this module for
	 *        the control panel side.
	 * @return string
	 * @attention
	 *     Controller fetches the list of modules from DB before. So, 'override' may not
	 *     be able to change the process.
	 */
	function getAdminIndex()
	{
		return null;
	}
	
	/**
	 * @public
	 * @brief Gets an array having menus for the side menu of the control panel.
	 * @return Complex Array
	 * @see /modules/legacy/admin/templates/blocks/legacy_admin_block_sidemenu.html
	 */
	function getAdminMenu()
	{
	}
}

/**
 * @public
 * @brief Used for adapting $xoopsModule to imitate XOOPS2 responses.
 * @remarks
 *    This class is the standard class implementing Legacy_AbstractModule, and is helpful
 *    to be used by Legacy_Controller. If a module doesn't define its sub-class of
 *    Legacy_AbstractModule, this class is used as generic Legacy_AbstractModule.
 */
class Legacy_ModuleAdapter extends Legacy_AbstractModule
{
	/**
	 * @private
	 * @brief bool
	 */
	var $_mAdminMenuLoadedFlag = false;
	
	/**
	 * @protected
	 * @brief Complex Array - cached
	 */
	var $mAdminMenu = null;
	
	/**
	 * @public
	 * @brief This method is called back by the action search feature in the control
	 *        panel.
	 * @param Legacy_ActionSearchArgs $searchArgs
	 * @return void
	 * @see Legacy_ActionSearchArgs
	 */
	function doActionSearch(&$searchArgs)
	{
		if(!is_object($searchArgs)) {
			return;
		}

		$this->mXoopsModule->loadAdminMenu();
		if(count($this->mXoopsModule->adminmenu) == 0 && !isset($this->mXoopsModule->modinfo['config']) ) {
			return;
		}
			
		//
		// Search preference
		//
		if(isset($this->mXoopsModule->modinfo['config'])&&count($this->mXoopsModule->modinfo['config'])>0) {
			$findFlag = false;
			foreach($searchArgs->getKeywords() as $word) {
				if (stristr(_PREFERENCES, $word) !== false) {
					$root =& XCube_Root::getSingleton();
					$searchArgs->addRecord($this->mXoopsModule->getVar('name'), $root->mController->getPreferenceEditUrl($this->mXoopsModule), _PREFERENCES);
					$findFlag = true;
					break;
				}
			}
			
			if (!$findFlag) {
				$configInfos=array();
				foreach($this->mXoopsModule->modinfo['config'] as $config) {
					if(isset($config['title']))
						$configInfos[]=@constant($config['title']);
					if(isset($config['description']))
						$configInfos[]=@constant($config['description']);
					if(isset($config['options'])&&count($config['options'])>0) {
						foreach($config['options'] as $key=>$val) {
							$configInfos[]=(@constant($key) ? @constant($key) : $key);
						}
					}
				}
	
				$findFlag=true;
				foreach($searchArgs->getKeywords() as $word) {
					$findFlag&=(stristr(implode(" ",$configInfos),$word)!==false);
				}
					
				if($findFlag) {
					$searchArgs->addRecord($this->mXoopsModule->getVar('name'),
					                  XOOPS_URL.'/modules/legacy/admin/index.php?action=PreferenceEdit&amp;confmod_id='.$this->mXoopsModule->getVar('mid'),
					                  _PREFERENCES );
				}
			}
		}
		
		//
		// Search AdminMenu
		//
		if(count($this->mXoopsModule->adminmenu)>0) {
			foreach($this->mXoopsModule->adminmenu as $menu) {
				$findFlag=true;
				foreach($searchArgs->getKeywords() as $word) {
					$tmpFlag=false;
					$tmpFlag|=(stristr($menu['title'],$word)!==false);

					// Search keyword
					if(isset($menu['keywords'])) {
						$keyword=is_array($menu['keywords']) ? implode(" ",$menu['keywords']) : $menu['keywords'];
						$tmpFlag|=(stristr($keyword,$word)!==false);
					}

					$findFlag&=$tmpFlag;
				}

				if($findFlag) {
					//
					// Create url string with absolute information.
					//
					$url="";
					if(isset($menu['absolute'])&&$menu['absolute']) {
						$url=$menu['link'];
					}
					else {
						$url=XOOPS_URL."/modules/".$this->mXoopsModule->getVar('dirname')."/".$menu['link'];
					}

					//
					// Add record
					//
					$searchArgs->addRecord($this->mXoopsModule->getVar('name'),$url,$menu['title']);
				}
			}
		}
		
		//
		// Search help
		//
		if ($this->mXoopsModule->hasHelp()) {
			$findFlag = false;
			
			foreach($searchArgs->getKeywords() as $word) {
				if (stristr(_HELP, $word) !== false) {
					$root =& XCube_Root::getSingleton();
					$searchArgs->addRecord($this->mXoopsModule->getVar('name'), $root->mController->getHelpViewUrl($this->mXoopsModule), _HELP);
					$findFlag = true;
					break;
				}
			}
			
			if (!$findFlag) {
				$root =& XCube_Root::getSingleton();
				$language = $root->mContext->getXoopsConfig('language');
				$helpfile = $this->mXoopsModule->getHelp();
				$dir = XOOPS_MODULE_PATH . "/" . $this->mXoopsModule->getVar('dirname') . "/language/" . $language. "/help";
	
				if (!file_exists($dir . "/" . $helpfile)) {
					$dir = XOOPS_MODULE_PATH . "/" . $this->mXoopsModule->getVar('dirname') . "/language/english/help";
						if (!file_exists($dir . "/" . $helpfile)) {
							return;
						}
				}
				$lines = file($dir . "/" . $helpfile);
				foreach ($lines as $line) {
					foreach($searchArgs->getKeywords() as $word) {
						if (stristr($line, $word) !== false) {
							$url = XOOPS_MODULE_URL . "/legacy/admin/index.php?action=Help&amp;dirname=" . $this->mXoopsModule->getVar('dirname');
							$searchArgs->addRecord($this->mXoopsModule->getVar('name'), $url, _HELP);
							return;
						}
					}
				}
			}
		}
	}

	function doLegacyGlobalSearch($queries, $andor, $max_hit, $start, $uid)
	{
		$ret = array();
		$results = $this->mXoopsModule->search($queries, $andor, $max_hit, $start, $uid);
		
		if (is_array($results) && count($results) > 0) {
			foreach ($results as $result) {
				$item = array();
				if (isset($result['image']) && strlen($result['image']) > 0) {
					$item['image'] = XOOPS_URL . '/modules/' . $this->mXoopsModule->get('dirname') . '/' . $result['image'];
				}
				else {
					$item['image'] = XOOPS_URL . '/images/icons/posticon2.gif';
				}
						
				$item['link'] = XOOPS_URL . '/modules/' . $this->mXoopsModule->get('dirname') . '/' . $result['link'];
				$item['title'] = $result['title'];
				$item['uid'] = $result['uid'];
						
				//
				// TODO If this service will come to web service, we should
				// change format from unixtime to string by timeoffset.
				//
				$item['time'] = isset($result['time']) ? $result['time'] : 0;
				
				$ret[] = $item;
			}
		}
		
		return $ret;
	}
	
	/**
	 * @public
	 * @brief [Final] Gets a value indicating whether this module has the page controller in
	 *        the control panel side.
	 * @return bool
	 */
	function hasAdminIndex()
	{
		$dmy =& $this->mXoopsModule->getInfo();
		return isset($this->mXoopsModule->modinfo['adminindex']) && $this->mXoopsModule->modinfo['adminindex'] != null;
  	}
	
	/**
	 * @public
	 * @brief Gets an absolute URL indicating the top page of this module for the control
	 *        panel side.
	 * @return string
	 */
	function getAdminIndex()
	{
		$dmy =& $this->mXoopsModule->getInfo();
		return XOOPS_MODULE_URL . '/' . $this->mXoopsModule->get('dirname') . '/' . $this->mXoopsModule->modinfo['adminindex'];
	}
	
	function getAdminMenu()
	{
		if ($this->_mAdminMenuLoadedFlag) {
			return $this->mAdminMenu;
		}
		
		$dmy =& $this->mXoopsModule->getInfo();
		$root =& XCube_Root::getSingleton();

		//
		// Load admin menu, and add preference menu by own judge.
		//
		$this->mXoopsModule->loadAdminMenu();
		if ($this->mXoopsModule->get('hasnotification')
		    || ($this->mXoopsModule->getInfo('config') && is_array($this->mXoopsModule->getInfo('config')))
		    || ($this->mXoopsModule->getInfo('comments') && is_array($this->mXoopsModule->getInfo('comments')))) {
				$this->mXoopsModule->adminmenu[] = array(
					'link' => $root->mController->getPreferenceEditUrl($this->mXoopsModule),
					'title' => _PREFERENCES,
					'absolute' => true);
		}
			
		if ($this->mXoopsModule->hasHelp()) {
			$this->mXoopsModule->adminmenu[] = array('link' =>  $root->mController->getHelpViewUrl($this->mXoopsModule),
			                              'title' => _HELP,
			                              'absolute' => true);
		}
		
		$this->_mAdminMenuLoadedFlag = true;
		
		if ($this->mXoopsModule->adminmenu) {
			foreach ($this->mXoopsModule->adminmenu as $menu) {
				if (!isset($menu['absolute']) || (isset($menu['absolute']) && $menu['absolute'] != true)) {
					$menu['link'] = XOOPS_MODULE_URL . '/' . $this->mXoopsModule->get('dirname') . '/' . $menu['link'];
				}
				$this->mAdminMenu[] = $menu;
			}
		}
		
		return $this->mAdminMenu;
	}
}
?>
